#include "OgreGLESDefaultHardwareBufferManager.h"

namespace Ogre
{
	GLESDefaultHardwareVertexBuffer::GLESDefaultHardwareVertexBuffer(size_t vertexSize,
																		size_t numVertices,
																		HardwareBuffer::Usage usage)
		: HardwareVertexBuffer(0, vertexSize, numVertices, usage, true, false) 
	{
		mpData = static_cast<unsigned char*>(OGRE_MALLOC_SIMD(mSizeInBytes, MEMCATEGORY_GEOMETRY));
	}

	GLESDefaultHardwareVertexBuffer::~GLESDefaultHardwareVertexBuffer()
	{
		OGRE_FREE_SIMD(mpData, MEMCATEGORY_GEOMETRY);
	}

	void* GLESDefaultHardwareVertexBuffer::lockImpl(size_t offset,
														size_t length,
														LockOptions options)
	{
		return mpData + offset;
	}

	void GLESDefaultHardwareVertexBuffer::unlockImpl(void)
	{
		// Nothing to do
	}

	void* GLESDefaultHardwareVertexBuffer::lock(size_t offset,
												size_t length,
												LockOptions options)
	{
		mIsLocked = true;
		return mpData + offset;
	}

	void GLESDefaultHardwareVertexBuffer::unlock(void)
	{
		mIsLocked = false;
		// Nothing to do
	}

	void GLESDefaultHardwareVertexBuffer::readData(size_t offset,
												size_t length,
												void* pDest)
	{
		assert((offset + length) <= mSizeInBytes);
		memcpy(pDest, mpData + offset, length);
	}

	void GLESDefaultHardwareVertexBuffer::writeData(size_t offset,
													size_t length,
													const void* pSource,
													bool discardWholeBuffer)
	{
		assert((offset + length) <= mSizeInBytes);
		// ignore discard, memory is not guaranteed to be zeroised
		memcpy(mpData + offset, pSource, length);
	}

	GLESDefaultHardwareIndexBuffer::GLESDefaultHardwareIndexBuffer(IndexType idxType,
																size_t numIndexes,
																HardwareBuffer::Usage usage)
		: HardwareIndexBuffer(0, idxType, numIndexes, usage, true, false)
		// always software, never shadowed
	{
		if (idxType == HardwareIndexBuffer::IT_32BIT)
		{
			OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
				"32 bit hardware buffers are not allowed in OpenGL ES.",
				"GLESDefaultHardwareIndexBuffer");
		}
        mpData = new unsigned char[mSizeInBytes];
	}

	GLESDefaultHardwareIndexBuffer::~GLESDefaultHardwareIndexBuffer()
    {
        delete [] mpData;
    }

	void* GLESDefaultHardwareIndexBuffer::lockImpl(size_t offset, size_t length, LockOptions options)
    {
        // Only for use internally, no 'locking' as such
        return mpData + offset;
    }

    void GLESDefaultHardwareIndexBuffer::unlockImpl(void)
    {
        // Nothing to do
    }

	void* GLESDefaultHardwareIndexBuffer::lock(size_t offset, size_t length, LockOptions options)
    {
        mIsLocked = true;
        return mpData + offset;
    }

	void GLESDefaultHardwareIndexBuffer::unlock(void)
    {
        mIsLocked = false;
        // Nothing to do
    }

	void GLESDefaultHardwareIndexBuffer::readData(size_t offset, size_t length, void* pDest)
	{
		assert((offset + lenght) <= mSizeInBytes);
		memcpy(pDest, mpData + offset, length);
	}

	void GLESDefaultHardwareIndexBuffer::writeData(size_t offset, size_t length, const void* pSource)
	{
		assert((offset + length) <= mSizeInBytes);
		// ignore discard, memory is not guaranteed to be zeroised
        memcpy(mpData + offset, pSource, length);
	}

	GLESDefaultHardwareBufferManagerBase::GLESDefaultHardwareBufferManagerBase()
    {
    }

	GLESDefaultHardwareBufferManagerBase::~GLESDefaultHardwareBufferManagerBase()
    {
        destroyAllDeclarations();
        destroyAllBindings();
    }

	HardwareVertexBufferSharedPtr
		: GLESDefaultHardwareBufferManagerBase::createVertexBuffer(size_t vertexSize,
		size_t numVerts, HardwareBuffer::Usage usage, bool useShadowBuffer)
	{
		return HardwareVertexBufferSharedPtr(
            new GLESDefaultHardwareVertexBuffer(vertexSize, numVerts, usage));
	}

	HardwareIndexBufferSharedPtr
        GLESDefaultHardwareBufferManagerBase::createIndexBuffer(HardwareIndexBuffer::IndexType itype,
        size_t numIndexes, HardwareBuffer::Usage usage, bool useShadowBuffer)
    {
        return HardwareIndexBufferSharedPtr(
            new GLESDefaultHardwareIndexBuffer(itype, numIndexes, usage));
    }

	Ogre::RenderToVertexBufferSharedPtr GLESDefaultHardwareBufferManagerBase::createRenderToVertexBuffer(void)
	{
		OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
	                "Cannot create RenderToVertexBuffer in GLESDefaultHardwareBufferManagerBase", 
	                "GLESDefaultHardwareBufferManagerBase::createRenderToVertexBuffer");

		Ogre::RenderToVertexBufferSharedPtr todo;
		return todo;
	}
}
